package pl.kosmowska.ewelina.client.app;

import pl.kosmowska.ewelina.client.app.activity.mappers.ApplicationActivityMapper;
import pl.kosmowska.ewelina.client.app.activity.mappers.ApplicationPlaceHistoryMapper;
import pl.kosmowska.ewelina.client.app.activity.places.BankStatementImportPlace;
import pl.kosmowska.ewelina.client.app.activity.places.CategoryPlace;
import pl.kosmowska.ewelina.client.app.activity.places.ChartPlace;
import pl.kosmowska.ewelina.client.app.activity.places.IncomeOutcomePlace;
import pl.kosmowska.ewelina.client.app.activity.places.IncomePlace;
import pl.kosmowska.ewelina.client.app.activity.places.InvestmentEditPlace;
import pl.kosmowska.ewelina.client.app.activity.places.InvestmentPlace;
import pl.kosmowska.ewelina.client.app.activity.places.LoanEditPlace;
import pl.kosmowska.ewelina.client.app.activity.places.LoanPlace;
import pl.kosmowska.ewelina.client.app.activity.places.OutcomeEditPlace;
import pl.kosmowska.ewelina.client.app.activity.places.OutcomePlace;
import pl.kosmowska.ewelina.client.app.activity.places.SavingsEditPlace;
import pl.kosmowska.ewelina.client.app.activity.places.SavingsPlace;
import pl.kosmowska.ewelina.client.app.activity.places.SignInPlace;
import pl.kosmowska.ewelina.client.app.activity.places.StockEditPlace;
import pl.kosmowska.ewelina.client.app.activity.places.StockPlace;
import pl.kosmowska.ewelina.client.app.requestfactory.ApplicationRequestFactory;
import pl.kosmowska.ewelina.client.app.requestfactory.dto.UserDataProxy;
import pl.kosmowska.ewelina.client.app.user.AuthEvent;
import pl.kosmowska.ewelina.client.app.user.AuthEvent.Auth;
import pl.kosmowska.ewelina.client.layout.Layout;
import pl.kosmowska.ewelina.client.views.BankStatementImportView;
import pl.kosmowska.ewelina.client.views.CategoryView;
import pl.kosmowska.ewelina.client.views.ChartView;
import pl.kosmowska.ewelina.client.views.IncomeOutcomeView;
import pl.kosmowska.ewelina.client.views.IncomeView;
import pl.kosmowska.ewelina.client.views.InvestmentEditView;
import pl.kosmowska.ewelina.client.views.InvestmentView;
import pl.kosmowska.ewelina.client.views.LoanEditView;
import pl.kosmowska.ewelina.client.views.LoanView;
import pl.kosmowska.ewelina.client.views.OutcomeEditView;
import pl.kosmowska.ewelina.client.views.OutcomeView;
import pl.kosmowska.ewelina.client.views.SavingsEditView;
import pl.kosmowska.ewelina.client.views.SavingsView;
import pl.kosmowska.ewelina.client.views.SignInView;
import pl.kosmowska.ewelina.client.views.StockEditView;
import pl.kosmowska.ewelina.client.views.StockView;
import pl.kosmowska.ewelina.client.views.impl.BankStatementImportViewImpl;
import pl.kosmowska.ewelina.client.views.impl.CategoryViewImpl;
import pl.kosmowska.ewelina.client.views.impl.ChartViewImpl;
import pl.kosmowska.ewelina.client.views.impl.IncomeOutcomeViewImpl;
import pl.kosmowska.ewelina.client.views.impl.IncomeViewImpl;
import pl.kosmowska.ewelina.client.views.impl.InvestmentEditViewImpl;
import pl.kosmowska.ewelina.client.views.impl.InvestmentViewImpl;
import pl.kosmowska.ewelina.client.views.impl.LeftSideViewImpl;
import pl.kosmowska.ewelina.client.views.impl.LoanEditViewImpl;
import pl.kosmowska.ewelina.client.views.impl.LoanViewImpl;
import pl.kosmowska.ewelina.client.views.impl.OutcomeEditViewImpl;
import pl.kosmowska.ewelina.client.views.impl.OutcomeViewImpl;
import pl.kosmowska.ewelina.client.views.impl.SavingsEditViewImpl;
import pl.kosmowska.ewelina.client.views.impl.SavingsViewImpl;
import pl.kosmowska.ewelina.client.views.impl.SignInViewImpl;
import pl.kosmowska.ewelina.client.views.impl.StockEditViewImpl;
import pl.kosmowska.ewelina.client.views.impl.StockViewImpl;
import pl.kosmowska.ewelina.client.views.widgets.AppLoadingView;

import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.gwt.user.client.ui.RootLayoutPanel;


public class ClientFactoryImpl implements ClientFactory {

	private Layout layout = new Layout();
	private Place defaultPlace = new SignInPlace();
	private static final EventBus eventBus = new SimpleEventBus();
	private final ApplicationRequestFactory requestFactory = GWT.create(ApplicationRequestFactory.class);
	private final ActivityMapper activityMapper = new ApplicationActivityMapper(this);
	private final ActivityManager activityManager = new ActivityManager(activityMapper, eventBus);
	private final ApplicationPlaceHistoryMapper historyMapper = GWT.create(ApplicationPlaceHistoryMapper.class);
	private final PlaceHistoryHandler placeHistoryHandler;
	private final PlaceController placeController = new PlaceController(eventBus);
	private UserDataProxy userData;
	private Boolean isLoggedIn;

	//views
	private final LeftSideViewImpl leftSide = new LeftSideViewImpl(this);
	private BankStatementImportView bankStatementImportView;
	private ChartView chartView;
	private OutcomeView outcomeView;  
	private IncomeView incomeView; 
	private IncomeOutcomeView incomeOutcomeView; 
	private LoanView loanView;
	private InvestmentView investmentView;
	private SavingsView savingsView;
	private SignInView signInView;
	private StockView stockView;
	private CategoryView categoryView;

	//create/edit views
	private OutcomeEditView outcomeEditView;
	private InvestmentEditView investmentEditView;
	private LoanEditView loanEditView;
	private SavingsEditView savingsEditView;
	private StockEditView stockEditView;

	//widgets
	private AppLoadingView appLoadingView;


	/**
	 * init
	 */
	public ClientFactoryImpl() {

		RootLayoutPanel.get().add(layout);

		activityManager.setDisplay(layout.getContentPanel());

		requestFactory.initialize(eventBus);

		historyMapper.setFactory(this);

		placeHistoryHandler = new PlaceHistoryHandler(historyMapper);
		placeHistoryHandler.register(placeController, eventBus, defaultPlace);

		layout.setClientFactory(this);
		layout.initMappers();

		placeHistoryHandler.handleCurrentHistory();
	}


	@Override
	public EventBus getEventBus() {
		return eventBus;
	}

	@Override
	public ApplicationRequestFactory getRequestFactory() {
		return requestFactory;
	}

	@Override
	public PlaceController getPlaceController() {
		return placeController;
	}

	@Override
	public void setUserData(UserDataProxy userData) {
		this.userData = userData;

		Auth auth = null;
		if (userData != null && 
				userData.getId() != null && 
				userData.getId().matches(".*([0-9]+).*") == true) {
			auth = Auth.LOGGEDIN;
			isLoggedIn = true;
		} else {
			auth = Auth.LOGGEDOUT;
			isLoggedIn = false;
		}
		eventBus.fireEvent(new AuthEvent(auth, userData));
	}

	@Override 
	public UserDataProxy getUserData() {
		return userData;
	}

	@Override
	public ActivityManager getActivityManager() {
		return activityManager;
	}

	@Override
	public Boolean getIsLoggedIn() {
		return isLoggedIn;
	}




	/***
	 * Used by the HistoryMapper { @link ApplicationPlaceHistoryMapper }
	 * Picked up by the historyMapper when needed.
	 * this way, I can send in objects like the requestFactory into them and use it
	 *  otherwise, the HistoryMapper runs decoupled with this here we can push objects into it.
	 */
	public SignInPlace.Tokenizer getSignInTokenizer() {
		return new SignInPlace.Tokenizer(requestFactory);
	}

	/**
	 * Used by the HistoryMapper { @link ApplicationPlaceHistoryMapper }
	 */

	@Override
	public BankStatementImportPlace.Tokenizer getBankStatementImportTokenizer() {
		return new BankStatementImportPlace.Tokenizer(requestFactory);
	}

	@Override
	public CategoryPlace.Tokenizer getCategoryEditTokenizer() {
		return new CategoryPlace.Tokenizer(requestFactory);
	}
	@Override
	public ChartPlace.Tokenizer getChartTokenizer() {
		return new ChartPlace.Tokenizer(requestFactory);
	}
	@Override
	public IncomeOutcomePlace.Tokenizer getIncomeOutcomeTokenizer() {
		return new IncomeOutcomePlace.Tokenizer(requestFactory);
	}

	@Override
	public OutcomePlace.Tokenizer getOutcomeTokenizer() {
		return new OutcomePlace.Tokenizer(requestFactory);
	}

	@Override
	public IncomePlace.Tokenizer getIncomeTokenizer() {
		return new IncomePlace.Tokenizer(requestFactory);
	}

	@Override
	public InvestmentEditPlace.Tokenizer getInvestmentEditTokenizer() {
		return new InvestmentEditPlace.Tokenizer(requestFactory);
	}

	@Override
	public InvestmentPlace.Tokenizer getInvestmentTokenizer() {
		return new InvestmentPlace.Tokenizer(requestFactory);
	}

	@Override
	public LoanEditPlace.Tokenizer getLoanEditTokenizer() {
		return new LoanEditPlace.Tokenizer(requestFactory);
	}

	@Override
	public LoanPlace.Tokenizer getLoanTokenizer() {
		return new LoanPlace.Tokenizer(requestFactory);
	}

	@Override
	public SavingsEditPlace.Tokenizer getSavingsEditTokenizer() {
		return new SavingsEditPlace.Tokenizer(requestFactory);
	}

	@Override
	public SavingsPlace.Tokenizer getSavingsTokenizer() {
		return new SavingsPlace.Tokenizer(requestFactory);
	}

	@Override
	public StockEditPlace.Tokenizer getStockEditTokenizer() {
		return new StockEditPlace.Tokenizer(requestFactory);
	}

	@Override
	public StockPlace.Tokenizer getStockTokenizer() {
		return new StockPlace.Tokenizer(requestFactory);
	}

	@Override
	public OutcomeEditPlace.Tokenizer getPanelTokenizer() {
		return new OutcomeEditPlace.Tokenizer(requestFactory);
	}

	@Override
	public BankStatementImportView getBankStatementImportView() {
		if(bankStatementImportView==null)
			bankStatementImportView = new BankStatementImportViewImpl();
		return bankStatementImportView;
	}

	@Override
	public ChartView getChartView() {
		if(chartView==null)
			chartView = new ChartViewImpl();
		return chartView;
	}

	@Override
	public OutcomeView getOutcomeView() {
		if(outcomeView==null)
			outcomeView = new OutcomeViewImpl();
		return outcomeView;
	}

	@Override
	public IncomeView getIncomeView() {
		if(incomeView==null)
			incomeView = new IncomeViewImpl();
		return incomeView;
	}

	@Override
	public IncomeOutcomeView getIncomeOutcomeView() {
		if(incomeOutcomeView==null)
			incomeOutcomeView = new IncomeOutcomeViewImpl();
		return incomeOutcomeView;
	}

	@Override
	public LoanView getLoanView() {
		if(loanView==null)
			loanView = new LoanViewImpl();
		return loanView;
	}

	@Override
	public InvestmentView getInvestmentView() {
		if(investmentView==null)
			investmentView = new InvestmentViewImpl();
		return investmentView;
	}

	@Override
	public SavingsView getSavingsView() {
		if(savingsView==null)
			savingsView = new SavingsViewImpl();
		return savingsView;
	}

	@Override
	public SignInView getSignInView() {
		if(signInView==null)
			signInView = new SignInViewImpl();
		return signInView;
	}

	@Override
	public StockView getStockView() {
		if(stockView==null)
			stockView = new StockViewImpl();
		return stockView;
	}

	@Override
	public OutcomeEditView getOutcomeEditView() {
		if(outcomeEditView==null)
			outcomeEditView = new OutcomeEditViewImpl();
		return outcomeEditView;
	}

	@Override
	public InvestmentEditView getInvestmentEditView() {
		if(investmentEditView==null)
			investmentEditView = new InvestmentEditViewImpl();
		return investmentEditView;
	}

	@Override
	public LoanEditView getLoanEditView() {
		if(loanEditView==null)
			loanEditView = new LoanEditViewImpl();
		return loanEditView;
	}

	@Override
	public SavingsEditView getSavingsEditView() {
		if(savingsEditView==null)
			savingsEditView = new SavingsEditViewImpl();
		return savingsEditView;
	}

	@Override
	public StockEditView getStockEditView() {
		if(stockEditView==null)
			stockEditView = new StockEditViewImpl();
		return stockEditView;
	}

	@Override
	public CategoryView getCategoryView() {
		if(categoryView==null)
			categoryView = new CategoryViewImpl();
		return categoryView;
	}


	@Override
	public LeftSideViewImpl getLeftSide() {
		return leftSide;
	}
	
	@Override
	public AppLoadingView getAppLoadingView(){
		if(appLoadingView==null){
			appLoadingView = new AppLoadingView();
		}
		return appLoadingView;
	}

}
